package net.danielseidl.ludumdare.ld48.tile;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.HashMap;
import java.util.logging.Logger;

import javax.imageio.ImageIO;

/**
 * For loading tiles used by the map in the game. Tile sets can be loaded by using 
 * the loadTilesFromFolder() method. Already stored tiles can be accessed by using 
 * the getTileFromStorage() method.
 *
 * @author    Daniel Seidl - info@daniel-seidl.net
 */
public class TileLoader
	{
	private final static Logger LOGGER = Logger.getLogger(TileLoader.class.getName());
	
	private HashMap<String, HashMap<String, Tile>> tileStorage = new HashMap<String, HashMap<String, Tile>>();
	
	/**
	 * Creates a new tile manager.
	 */
	public TileLoader()
		{
		this.loadTilesFromFolder("default");
		}
	
	/**
	 * Loads all saved tiles from the given folders into the tile storage.
	 * @param sets The folders inside the gfx/tiles folder.
	 */
	public void loadTileSets(String[] sets)
		{
		for (String set : sets)
			{
			this.loadTilesFromFolder(set);
			}
		}
	
	/**
	 * Loads all saved tiles from one folder into the tile storage.
	 * @param folder The folder inside the gfx/tiles folder.
	 */
	public void loadTilesFromFolder(String folder)
		{
		if (!this.tileStorage.containsKey(folder))
			{
			LOGGER.info("loading tiles from folder '" + folder +"'");
			
			// Create an new hash table for the tiles from this folder.
			HashMap<String, Tile> tiles = new HashMap<String, Tile>();
			
			// Load all the tiles from the folder...
			File dir = new File("gfx/tiles/" + folder);

			File tileData;
			String tileName;
			
			String[] fileList = dir.list(new FilenameFilter()
				{
			    public boolean accept(File d, String name)
			    	{
			       return name.endsWith(".png");
			    	}
				});
			
			// Create a tile object for every tile in this folder and put the tile
			// object into the hash table.
			for(String t : fileList)
				{
				try 
					{
					tileData = new File("gfx/tiles/" + folder + "/" + t);
					tileName = t.split(".png")[0];
					tiles.put(tileName, new Tile(folder, tileName, ImageIO.read(tileData)));
					}
				catch (IOException e)
					{
					LOGGER.warning("unable to load critical image 'gfx/tiles/" + folder + "/" + t + ".png'");
					}
				}
			
			// At the end put the created hash table into the storage.
			this.tileStorage.put(folder, tiles);
			}
		}
	
	/**
	 * Looks for a tile stored with the given name in the tile storage. If a tile
	 * is found it is returned. If there's no tile with the given name an exception
	 * is thrown and has to be catched.
	 * @param tileName The name of the tile.
	 * @return The tile as a tile object.
	 * @throws TileException If the tile is not stored in the tile storage.
	 */
	public Tile getTileFromStorage(String tileName) throws TileException
		{
		String[] splitted = tileName.split("#");
		Tile tile = this.tileStorage.get(splitted[0]).get(splitted[1]);
		if (tile == null)
			{
			throw new TileException("tile " + tileName + " has not been found in the storage");
			}
		else
			{
			return tile;
			}
		}	
	}